//回调函数
//通过函数指针调用的函数。如果把函数的指针（地址）作为参数传递给另一个函数，当这个指针被用来调用其所指向的函数时，我们就说这是回调函数。
//回调函数不是由该函数的实现方直接调用，而是在特定的事件或条件发生时由另一方调用的，用于对该事件或条件进行响应
//void qsort(void* base, //待排序的数据的起始位置
//           size_t num, //待排序的数据元素个数
//           size_t width, //待排序的数据元素的大小（单位是字节）
//           int(*cmp)(const void* e1, const void* e2)) //函数指针-比较函数（不同类型数据比较方式有差异）
//           前面个数据大就返回大于零的数，前面数据小就返回小于零的数，等于返回零（按从小到大排序）
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Stu
{
    char name[20];
    int age;
};

int cmp_int(const void* e1, const void* e2)
{//void*可接受任意类型的地址，但不能解引用也不能加减
    return (*(int*)e1 - *(int*)e2);
}

int cmp_stu_by_name(const void* e1, const void* e2)
{
    return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);//从第一个字符开始比，比较ascll码值
}

int cmp_stu_by_age(const void* e1, const void* e2)
{
    return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

void test1()//整形排序
{
    int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr, sz, sizeof(arr[0]), cmp_int);

    int i = 0;
    for(i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
}

void test2()//排结构体
{
    struct Stu s[] = {{"zhangsan", 15}, {"lisi", 30}, {"wangwu", 25}};
    int sz = sizeof(s) / sizeof(s[0]);
    qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
    
    int i = 0;
    for(i = 0; i < 3; i++)
    {
        printf("%s ", s[i].name);
    }

    printf("\n");

    qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
    
    for(i = 0; i < 3; i++)
    {
        printf("%d ", s[i].age);
    }
}

int main()
{
    test1();
    printf("\n");
    test2();
    return 0;
}